package com.demo.rabbitmq.config;

import com.demo.rabbitmq.model.properties.RabbitMQFirstProterty;
import com.demo.rabbitmq.model.properties.RabbitMQProperty;
import com.demo.rabbitmq.model.properties.RabbitMQSecondProterty;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 多个RabbitMQ实例配置
 */
@Slf4j
@ConditionalOnProperty(name = "spring.rabbitmq.multi-server.enabled", havingValue = "true")
@Configuration
public class RabbitMQMultiServerConfig {

    @Resource
    private RabbitMQFirstProterty rabbitMQFirstProterty;
    @Resource
    private RabbitMQSecondProterty rabbitMQSecondProterty;

    @Bean(name = "firstConnectionFactory")
    @Primary
    public ConnectionFactory firstConnectionFactory() {
        log.info("firstRabbitMQ connectionFactory初始化");
        return connectionFactory(rabbitMQFirstProterty);
    }

    @Bean(name = "firstRabbitTemplate")
    @Primary
    public RabbitTemplate firstRabbitTemplate(@Qualifier("firstConnectionFactory") ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        routeBind(rabbitTemplate, "multi_server_queue1", "multi_server_exchange1", "multi_server_queue_routing_key1");
        return rabbitTemplate;
    }

    //命名mq1的RabbitListenerContainerFactory,如果项目中只有一个mq则不必如此
    @Bean("firstRabbitListenerContainerFactory")
    public SimpleRabbitListenerContainerFactory firstRabbitListenerContainerFactory(@Qualifier("firstConnectionFactory") ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
        listenerContainerFactory.setConnectionFactory(connectionFactory);
        return listenerContainerFactory;
    }

    @Bean(name = "secondConnectionFactory")
    public ConnectionFactory secondConnectionFactory() {
        log.info("secondRabbitMQ connectionFactory初始化");
        return connectionFactory(rabbitMQSecondProterty);
    }

    @Bean(name = "secondRabbitTemplate")
    public RabbitTemplate secondRabbitTemplate(@Qualifier("secondConnectionFactory") ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        routeBind(rabbitTemplate, "multi_server_queue2", "multi_server_exchange2", "multi_server_queue_routing_key2");
        return rabbitTemplate;
    }

    //命名mq2的RabbitListenerContainerFactory,如果项目中只有一个mq则不必如此
    @Bean("secondRabbitListenerContainerFactory")
    public SimpleRabbitListenerContainerFactory secondRabbitListenerContainerFactory(@Qualifier("secondConnectionFactory") ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
        listenerContainerFactory.setConnectionFactory(connectionFactory);
        return listenerContainerFactory;
    }

    private CachingConnectionFactory connectionFactory(RabbitMQProperty rabbitMQProperty) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(rabbitMQProperty.getHost());
        connectionFactory.setPort(rabbitMQProperty.getPort());
        connectionFactory.setUsername(rabbitMQProperty.getUsername());
        connectionFactory.setPassword(rabbitMQProperty.getPassword());
        return connectionFactory;
    }

    private void routeBind(RabbitTemplate rabbitTemplate, String queueName, String exchangeName, String routingKey) {
        // 创建队列
        Queue queue = new Queue(queueName);
        // 创建交换机
        DirectExchange exchange = new DirectExchange(exchangeName);
        // 绑定
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);

        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate);
        rabbitAdmin.declareQueue(queue);
        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareBinding(binding);
    }
}
